module klang.编译.核心.核心_;
import 全局;
import std.conv: ·to = to;
import std.functional: ·fd = toDelegate;
import klang.编译.类型.枚举值.枚举值_: 字符_, 比较结果_;
alias 整数_ = long;
alias 获取正规文件名函数_ = dstring delegate(dstring);
alias 比较器_(T) = 比较结果_ delegate(T, T);
alias 相等比较器_(T) = bool delegate(T, T);
alias 映射类型_(T) = T delegate(T);
class 词典_(T) {
    T[dstring] 原型;
    this() { this.原型 = ··null!(T[dstring]); }
    immutable this() { this.原型 = ··null!(immutable(T[dstring])); }
    shared this() { this.原型 = ··null!(shared(T[dstring])); }
    this(T[dstring] ·this) {
        this.原型 = ·this;
    }
    const this(const(T[dstring]) ·this) {
        this.原型 = ·this;
    }
    immutable this(immutable(T[dstring]) ·this) {
        this.原型 = ·this;
    }
    shared this(shared(T[dstring]) ·this) {
        this.原型 = ·this;
    }
    ·U opCast(·U)() {
        if (this is null)
            return null;
        ·U ·ret = new ·U();
        ·ret.原型 = ·to!(typeof(·ret.原型))(原型);
        return ·ret;
    }
    bool 具有(dstring 键) {
        return .具有!(T, dstring)(this.原型, 键) !is ··null!(T*);
    }
    void p·设置(dstring 键, T 值) {
        this.原型[键] = 值;
    }
    T 获取(dstring 键) {
        return this.原型[键];
    }
    void p·循环每个(void delegate(T, dstring) 回调) {
        foreach (dstring 键, T 值; this.原型) {
            回调(值, 键);
        }
    }
    void 清除() {
        .清除!(T, dstring)(this.原型);
    }
    const(dstring[]) 键组() {
        return .键组!(T, dstring)(this.原型);
    }
    const(T[]) 值组() {
        return .值组!(T, dstring)(this.原型);
    }
    bool 删除值(dstring 键) {
        return .删除值!(T, dstring)(this.原型, 键);
    }
    const(size_t) 大小() {
        return this.原型.length;
    }
    alias 原型 this;
}
class 去重数组_(T) {
    T[] 数据;
    dstring 输出;
    bool 有更新;
    this() {
        this.数据 = .创建数组!(T)();
        this.输出 = ··null!(dstring);
        this.有更新 = false;
    }
    void p·设置(T v) {
        if (.pushIfUnique!(T)(this.数据, v)) {
            this.有更新 = true;
        }
    }
    void p·合并(去重数组_!(T) 源) {
        foreach (T v; 源.数据) {
            this.p·设置(v);
        }
    }
    bool p·具有(T v) {
        return .查找数组索引!(T)(this.数据, (T e) { return e == v; }) != -1;
    }
    T p·查找(T v) {
        long i = .查找数组索引!(T)(this.数据, (T e) { return e == v; });
        if (i == -1) {
            return ··null!(T);
        }
        return this.数据[i];
    }
    T 最后一个() {
        return this.数据[this.数据.length - 1];
    }
    bool 是空的() {
        return this.数据.length == 0;
    }
    size_t 大小() {
        return this.数据.length;
    }
    dstring 去重排序输出() {
        if ((this.输出 !is ··null!(dstring)) && !this.有更新) {
            return this.输出;
        }
        if (this.是空的()) {
            return ""d;
        }
        dstring[] 输出数组 = .映射!(T, dstring)(this.数据, (T v, size_t _) { return ·to!(dstring)(v); });
        if (输出数组.length > 0) {
            输出数组 = .排序!(dstring)(输出数组, (dstring a, dstring b) { return .逐字比较(a, b); });
            this.输出 = .连接(输出数组, ","d);
        }
        else {
            this.输出 = ""d;
        }
        this.有更新 = false;
        return this.输出;
    }
}
class 简单链表_ {
    dchar[dchar] 值;
    简单链表_[dchar] 下个;
    this() { }
    this(dchar 值) {
        this.值 = [值 : 值];
        this.下个 = ··null!(简单链表_[dchar]);
    }
}
class 分割结果_ {
    dstring first;
    dstring second;
    this() { }
    this(dstring first, dstring second = ··null!(dstring)) {
        this.first = first;
        this.second = second;
    }
}
T[] 创建数组(T)() {
    return (cast(T[])([]));
}
T 返回零值(T)() {
    return ··null!(T);
}
词典_!(T) 创建词典(T)() {
    return new 词典_!(T)();
}
词典_!(T) 创建词典从关联数组(T)(T[dstring] 数据) {
    return new 词典_!(T)(数据);
}
词典_!(T) 克隆词典(T)(词典_!(T) map) {
    词典_!(T) ret = .创建词典!(T)();
    map.p·循环每个((T v, dstring k) {
        ret.p·设置(k, v);
    });
    return ret;
}
T[] 克隆数组(T)(T[] 数组) {
    T[] 结果 = .创建数组!(T)();
    foreach (T v; 数组) {
        .追加!(T)(结果, v);
    }
    return 结果;
}
T 字节转换(T, U)(U V) {
    U[1] VP = [V];
    T[1] RP;
    .·memcpy(RP.ptr, VP.ptr, V.sizeof);
    return RP[0];
}
size_t 长度(T)(T[] arr = ··null!(T[])) {
    if (arr !is ··null!(T[])) {
        return arr.length;
    }
    return 0;
}
long 最大(long a, long b) {
    if (a >= b) {
        return a;
    }
    return b;
}
long 最小(long a, long b) {
    if (a <= b) {
        return a;
    }
    return b;
}
U 循环每个(T, U)(T[] arr, U delegate(T, size_t) 回调) {
    if (arr !is ··null!(T[])) {
        foreach (size_t i, T v; arr) {
            U 结果 = 回调(v, i);
            if (结果 !is ··null!(U)) {
                return 结果;
            }
        }
    }
    return ··null!(U);
}
U[] 映射(T, U)(T[] arr, U delegate(T, size_t) 回调) {
    U[] 结果 = [];
    if (arr !is ··null!(T[])) {
        结果.length = arr.length;
        {
            for (int i = 0; i < arr.length; ++i) {
                结果[i] = 回调(arr[i], i);
            }
        }
    }
    return 结果;
}
U[] 映射定义的(T, U)(T[] arr, U delegate(T, size_t) 回调) {
    U[] 结果 = [];
    if (arr !is ··null!(T[])) {
        {
            for (int i = 0; i < arr.length; ++i) {
                U 回调结果 = 回调(arr[i], i);
                if (回调结果 !is ··null!(U)) {
                    .追加!(U)(结果, 回调结果);
                }
            }
        }
    }
    return 结果;
}
long 查找字符索引(dstring 主体文本, 字符_ 搜索字符, size_t 起点 = ··null!(size_t)) {
    long 开始位置 = 0;
    if (起点 !is ··null!(size_t)) {
        开始位置 = 起点;
    }
    {
        for (long i = 开始位置; i < 主体文本.length; ++i) {
            immutable(dchar) 源字符 = 主体文本[i];
            if (源字符 == 搜索字符) {
                return i;
            }
        }
    }
    return -1;
}
void 分割文本(dstring 主体文本, 字符_ 分隔符, ref 分割结果_ 结果) {
    long i = .查找字符索引(主体文本, 分隔符);
    if (i != -1) {
        结果 = new 分割结果_(主体文本[0 .. i], 主体文本[(i + 1) .. $]);
    }
    else {
        结果 = new 分割结果_(主体文本);
    }
}
long 查找索引(dstring 主体文本, dstring 搜索文本, size_t 起点 = ··null!(size_t)) {
    long 开始位置 = 0;
    if (起点 !is ··null!(size_t)) {
        开始位置 = 起点;
    }
    if (搜索文本 is ··null!(dstring)) {
        return -1;
    }
    immutable(dchar) 开始字符 = 搜索文本[0];
    {
        for (long i = 开始位置; i < 主体文本.length; ++i) {
            immutable(dchar) 源字符 = 主体文本[i];
            if (源字符 == 开始字符) {
                if (搜索文本.length == 1) {
                    return i;
                }
                if (主体文本.length < i + 搜索文本.length) {
                    return -1;
                }
                dstring 分割文本 = 主体文本[i .. i + 搜索文本.length];
                if (分割文本 == 搜索文本) {
                    return i;
                }
            }
        }
    }
    return -1;
}
long 查找数组索引(T)(T[] 数组, bool delegate(T) 回调) {
    {
        for (int i = 0; i < 数组.length; ++i) {
            if (回调(数组[i])) {
                return i;
            }
        }
    }
    return -1;
}
T 查找(T)(T[] 数组, bool delegate(T) 回调) {
    {
        for (int i = 0; i < 数组.length; ++i) {
            if (回调(数组[i])) {
                return 数组[i];
            }
        }
    }
    return ··null!(T);
}
T 最后一个(T)(T[] 数组 = ··null!(T[])) {
    if (数组 is ··null!(T[])) {
        return ··null!(T);
    }
    if (数组.length == 0) {
        return ··null!(T);
    }
    return 数组[数组.length - 1];
}
/** indexOfAnyCharCode */
long 查找任意字符代码的索引(dstring 文字, int[] 字符代码组, long 开始 = 0) {
    {
        for (long i = 开始; i < 文字.length; ++i) {
            int 值 = (cast(int)(文字[i]));
            if (.包含!(int)(字符代码组, 值, (int a, int b) { return a == b; })) {
                return i;
            }
        }
    }
    return -1;
}
T[] 过滤(T)(T[] 数组, bool delegate(T) 谓词) {
    if (数组 !is ··null!(T[])) {
        size_t 长 = 数组.length;
        int i = 0;
        while(i < 长 && 谓词(数组[i])) {
            ++i;
        }
        if (i < 长) {
            T[] 结果 = 数组[0 .. i];
            ++i;
            while(i < 长) {
                T 值 = 数组[i];
                if (谓词(值)) {
                    结果 = .追加!(T)(结果, 值);
                }
                ++i;
            }
            return 结果;
        }
    }
    return 数组;
}
T[] 排序(T)(T[] 数组, 比较结果_ delegate(T, T) 比较) {
    if (数组.length == 0 || 数组.length == 1) {
        return 数组;
    }
    T[] 结果数组 = 数组;
    {
        for (int i = 0; i < 结果数组.length; ++i) {
            {
                for (int j = 0; j + 1 < 结果数组.length; ++j) {
                    if (比较(结果数组[j], 结果数组[j + 1]) == 比较结果_.大于) {
                        T 临时 = 结果数组[j];
                        结果数组[j] = 结果数组[j + 1];
                        结果数组[j + 1] = 临时;
                    }
                }
            }
        }
    }
    return 结果数组;
}
T[] 扁平化(T)(T[][] 数组) {
    T[] 结果 = [];
    foreach (T[] v; 数组) {
        结果 = .追加!(T)(结果, v);
    }
    return 结果;
}
U[] 扁平化映射组(T, U)(T[] 数组 = ··null!(T[]), U[] delegate(T, size_t) cb = ··null!(U[] delegate(T, size_t))) {
    if (数组 is ··null!(T[])) {
        return ··null!(U[]);
    }
    U[] 结果 = .创建数组!(U)();
    if (数组 !is ··null!(T[])) {
        {
            for (int i = 0; i < 数组.length; ++i) {
                U[] v = cb(数组[i], i);
                if (v !is ··null!(U[])) {
                    结果 = .追加!(U)(结果, v);
                }
            }
        }
    }
    if (结果.length == 0) {
        return ··null!(U[]);
    }
    return 结果;
}
U[] 扁平化映射(T, U)(T[] 数组, U delegate(T, size_t) cb) {
    U[] 结果 = [];
    if (数组 !is ··null!(T[])) {
        {
            for (int i = 0; i < 数组.length; ++i) {
                U v = cb(数组[i], i);
                if (v !is ··null!(U)) {
                    结果 = .追加!(U)(结果, v);
                }
            }
        }
    }
    return 结果;
}
dstring 替换(dstring 主体文本, dstring 查找文本, dstring 替换文本) {
    dstring 前面 = ""d;
    long 索引 = .查找索引(主体文本, 查找文本);
    while(索引 != -1) {
        前面 ~= 主体文本[0 .. 索引];
        前面 ~= 替换文本;
        主体文本 = 主体文本[索引 + 查找文本.length .. $];
        索引 = .查找索引(主体文本, 查找文本);
    }
    return 前面 ~ 主体文本;
}
dstring[] 分割(dstring 主体文本, dstring[] 分割符) {
    long 索引 = -1;
    dstring 使用的分割符 = 分割符[0];
    foreach (dstring 当前分割; 分割符) {
        索引 = .查找索引(主体文本, 当前分割);
        if (索引 != -1) {
            使用的分割符 = 当前分割;
            break;
        }
    }
    dstring[] 结果 = [];
    while(索引 != -1) {
        if (索引 != 0) {
            结果 = .追加!(dstring)(结果, 主体文本[0 .. 索引]);
        }
        主体文本 = 主体文本[索引 + 使用的分割符.length .. $];
        foreach (dstring 当前分割; 分割符) {
            索引 = .查找索引(主体文本, 当前分割);
            if (索引 != -1) {
                使用的分割符 = 当前分割;
                break;
            }
        }
    }
    if (主体文本 !is ··null!(dstring)) {
        结果 = .追加!(dstring)(结果, 主体文本);
    }
    return 结果;
}
dstring[] 按字符分割(dstring 主体文本, 字符_ 分割符) {
    long 索引 = .查找字符索引(主体文本, 分割符);
    dstring[] 结果 = .创建数组!(dstring)();
    if (索引 == -1) {
        .追加!(dstring)(结果, 主体文本);
        return 结果;
    }
    while(索引 != -1) {
        if (索引 != 0) {
            .追加!(dstring)(结果, 主体文本[0 .. 索引]);
        }
        主体文本 = 主体文本[索引 + 1 .. $];
        索引 = .查找字符索引(主体文本, 分割符);
    }
    if (主体文本 != ""d) {
        .追加!(dstring)(结果, 主体文本);
    }
    return 结果;
}
dstring 连接(dstring[] 文本数组, dstring 连接符 = ··null!(dstring)) {
    if (文本数组.length == 0) {
        return ""d;
    }
    if (文本数组.length == 1) {
        return 文本数组[0];
    }
    if (连接符 is ··null!(dstring)) {
        连接符 = ", "d;
    }
    dstring 结果 = ""d;
    dstring 最后一个 = 文本数组[文本数组.length - 1];
    {
        for (int i = 0; i < 文本数组.length - 1; ++i) {
            结果 ~= 文本数组[i] ~ 连接符;
        }
    }
    return 结果 ~ 最后一个;
}
long 从后查找索引(dstring 主体文本, dstring 搜索文本, long 起点 = ··null!(long)) {
    if (搜索文本.length == 0) {
        return -1;
    }
    long 开始位置 = 主体文本.length - 1;
    if (起点 !is ··null!(long)) {
        开始位置 = 起点;
    }
    if (开始位置 < 0) {
        return -1;
    }
    long 条件长度 = 搜索文本.length - 1;
    immutable(dchar) 开始字符 = 搜索文本[条件长度];
    {
        for (long i = 开始位置; i >= 条件长度; --i) {
            immutable(dchar) 源字符 = 主体文本[i];
            if (源字符 == 开始字符) {
                if (搜索文本.length == 1) {
                    return i;
                }
                dstring 分割文本 = 主体文本[i - 条件长度 .. i + 1];
                if (分割文本 == 搜索文本) {
                    return i - 条件长度;
                }
            }
        }
    }
    return -1;
}
long 从后查找字符索引(dstring 主体文本, dchar 搜索字符, long 起点 = ··null!(long)) {
    long 开始位置 = 主体文本.length - 1;
    if (起点 !is ··null!(long)) {
        if (起点 > 开始位置) {
            起点 = 开始位置;
        }
        开始位置 = 起点;
    }
    if (开始位置 < 0) {
        return -1;
    }
    {
        for (long i = 开始位置; i >= 0; --i) {
            immutable(dchar) 源字符 = 主体文本[i];
            if (源字符 == 搜索字符) {
                return i;
            }
        }
    }
    return -1;
}
bool 相等值(T)(T a, T b) {
    return a == b;
}
/**
 * Compare the equality of two strings using a case-sensitive ordinal comparison.
 *
 * Case-sensitive comparisons compare both strings one code-point at a time using the integer
 * 值 of each code-point 输出之后转换函数组 applying `toUpperCase` to each string. We always map both
 * strings to their upper-case form as some unicode characters do not properly round-trip to
 * lowercase (such as `ẞ` (German sharp capital s)).
 */
bool 相等文本不区分大小写(dstring a, dstring b) {
    return a == b || (a !is ··null!(dstring)) && (b !is ··null!(dstring)) && .文本转大写(a) == .文本转大写(b);
}
/**
 * Compare two strings using a case-insensitive ordinal comparison.
 *
 * Ordinal comparisons are based on the difference between the unicode code points of both
 * strings. Characters with multiple unicode representations are considered unequal. Ordinal
 * comparisons provide predictable ordering, but place "a" 输出之后转换函数组 "B".
 *
 * Case-insensitive comparisons compare both strings one code-point at a time using the integer
 * 值 of each code-point 输出之后转换函数组 applying `toUpperCase` to each string. We always map both
 * strings to their upper-case form as some unicode characters do not properly round-trip to
 * lowercase (such as `áºž` (German sharp capital s)).
 */
比较结果_ 比较文本不区分大小写(dstring a, dstring b) {
    if (a == b) {
        return 比较结果_.等于;
    }
    if (a is ··null!(dstring)) {
        return 比较结果_.小于;
    }
    if (b is ··null!(dstring)) {
        return 比较结果_.大于;
    }
    a = .文本转大写(a);
    b = .文本转大写(b);
    比较结果_ 结果 = a == b ? 比较结果_.等于 : .逐字比较(a, b);
    return 结果;
}
比较结果_ 比较文本区分大小写(dstring a, dstring b) {
    if (a == b) {
        return 比较结果_.等于;
    }
    if (a is ··null!(dstring)) {
        return 比较结果_.小于;
    }
    if (b is ··null!(dstring)) {
        return 比较结果_.大于;
    }
    比较结果_ 结果 = a == b ? 比较结果_.等于 : .逐字比较(a, b);
    return 结果;
}
比较结果_ 逐字比较(dstring a, dstring b) {
    long 长 = .最小(a.length, b.length);
    {
        for (int i = 0; i < 长; ++i) {
            immutable(dchar) ai = a[i];
            immutable(dchar) bi = b[i];
            if (ai != bi) {
                return ai > bi ? 比较结果_.大于 : ai < bi ? 比较结果_.小于 : 比较结果_.等于;
            }
        }
    }
    return a.length > b.length ? 比较结果_.大于 : a.length < b.length ? 比较结果_.小于 : 比较结果_.等于;
}
比较结果_ 比较器比较值(long a, long b) {
    return a > b ? 比较结果_.大于 : a < b ? 比较结果_.小于 : 比较结果_.等于;
}
bool arrayIsHomogeneous(T)(T[] array, bool delegate(T, T) comparer) {
    if (array.length < 2) {
        return true;
    }
    T first = array[0];
    {
        for (int i = 1; i < array.length; ++i) {
            T target = array[i];
            if (!comparer(first, target)) {
                return false;
            }
        }
    }
    return true;
}
bool 部分(T)(T[] 数组, bool delegate(T) 谓词 = ··null!(bool delegate(T))) {
    if (数组 !is ··null!(T[])) {
        if (谓词 !is ··null!(bool delegate(T))) {
            foreach (T v; 数组) {
                if (谓词(v)) {
                    return true;
                }
            }
        }
        else {
            return 数组.length > 0;
        }
    }
    return false;
}
bool 每个(T)(T[] 数组, bool delegate(T) 谓词) {
    if (数组 !is ··null!(T[])) {
        foreach (T v; 数组) {
            if (!谓词(v)) {
                return false;
            }
        }
    }
    return true;
}
bool 每个数组成员(T)(T[] 数组, bool delegate(T, size_t) 谓词) {
    if (数组 !is ··null!(T[])) {
        foreach (size_t i, T v; 数组) {
            if (!谓词(v, i)) {
                return false;
            }
        }
    }
    return true;
}
bool 包含一部分(T)(T[] 数组, bool delegate(T) 谓词) {
    foreach (T v; 数组) {
        if (谓词(v)) {
            return true;
        }
    }
    return false;
}
bool 包含(T)(T[] 数组, T 值, 相等比较器_!(T) 比较器 = (T a, T b) { return a == b; }) {
    if ((数组 !is ··null!(T[])) && 数组.length > 0) {
        foreach (T v; 数组) {
            if (比较器(v, 值)) {
                return true;
            }
        }
    }
    return false;
}
bool pushIfUnique(T)(ref T[] array, T toAdd, 相等比较器_!(T) equalityComparer = (T a, T b) { return a == b; }) {
    if (.包含!(T)(array, toAdd, cast(相等比较器_!(T))(equalityComparer))) {
        return false;
    }
    else {
        .追加!(T)(array, toAdd);
        return true;
    }
}
T[] appendIfUnique(T)(ref T[] array, T toAdd, 相等比较器_!(T) equalityComparer = ··null!(相等比较器_!(T))) {
    if (array !is ··null!(T[])) {
        if (equalityComparer !is ··null!(相等比较器_!(T))) {
            .pushIfUnique!(T)(array, toAdd, cast(相等比较器_!(T))(equalityComparer));
        }
        else {
            .pushIfUnique!(T)(array, toAdd);
        }
        return array;
    }
    else {
        array = [toAdd];
        return array;
    }
}
T[] sliceAfter(T)(T[] arr, T value) {
    long index = .查找数组索引!(T)(arr, (T v) { return v == value; });
    return arr[index .. $];
}
void getRangesWhere(T)(T[] arr, bool delegate(T) pred, void delegate(long, long) cb) {
    long start = -1;
    {
        for (int i = 0; i < arr.length; ++i) {
            if (pred(arr[i])) {
                start = start == -1 ? i : start;
            }
            else {
                if (start != -1) {
                    cb(start, i);
                    start = -1;
                }
            }
        }
    }
    if (start != -1) {
        cb(start, arr.length);
    }
}
const(dchar) 转为小写(const(dchar) ch) {
    if (ch >= 字符_.A && ch < 字符_.Z) {
        return ch - 字符_.A + 字符_.a;
    }
    return ch;
}
const(dchar) 转为大写(const(dchar) ch) {
    if (ch >= 字符_.a && ch < 字符_.z) {
        return ch + 字符_.A - 字符_.a;
    }
    return ch;
}
dstring 裁剪文本(dstring s = ""d) {
    if (s == ""d) {
        return ""d;
    }
    return .trimEndImpl(.trimStartImpl(s));
}
/** Does not include line breaks. For that, see isWhiteSpaceLike. */
bool 是空白单行字符(const(dchar) ch) {
    // Note: nextLine is in the Zs space, and should be considered to be a whitespace.
    // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript.
    return ch == 字符_.空格 || ch == 字符_.水平制表 || ch == 字符_.垂直制表 || ch == 字符_.分页 || ch == 字符_.不间断空格 || ch == 字符_.下一行 || ch == 字符_.欧甘符 || ch >= 字符_.半角四空 && ch <= 字符_.零宽度空格 || ch == 字符_.窄无换行空格 || ch == 字符_.窄无换行空格 || ch == 字符_.表意空格 || ch == 字符_.字节顺序标记;
}
bool 是换行类的(const(dchar) ch) {
    // ES5 7.3:
    // The ECMAScript line terminator characters are listed in Table 3.
    //     Table 3: Line Terminator Characters
    //     Code Unit Value     Name                    Formal Name
    //     \u000A              Line Feed               <LF>
    //     \u000D              Carriage Return         <CR>
    //     \u2028              Line separator          <LS>
    //     \u2029              Paragraph separator     <PS>
    // Only the characters in Table 3 are treated as line terminators. Other new line or line
    // breaking characters are treated as white space but not as line terminators.
    return ch == 字符_.换行符 || ch == 字符_.回车符 || ch == 字符_.行分隔符 || ch == 字符_.段落分隔符;
}
bool 是空白或换行(const(dchar) ch) {
    return .是空白单行字符(ch) || .是换行类的(ch);
}
bool 是数字类的(const(dchar) ch) {
    return ch >= 字符_.数_0 && ch <= 字符_.数_9;
}
bool 是十进制字符(immutable(dchar) ch) {
    return ch >= 字符_.数_0 && ch <= 字符_.数_9;
}
bool 是八进制字符(immutable(dchar) ch) {
    return ch >= 字符_.数_0 && ch <= 字符_.数_7;
}
bool 是十六进制字符(const(dchar) ch) {
    return .是数字类的(ch) || ch >= 字符_.a && ch <= 字符_.f || ch >= 字符_.A && ch <= 字符_.F;
}
dstring trimEndImpl(dstring s) {
    long end = s.length - 1;
    while(end >= 0) {
        if (!.是空白或换行(s[end])) {
            break;
        }
        --end;
    }
    return s[0 .. end + 1];
}
dstring trimStartImpl(dstring s) {
    long pot = 0;
    while(pot < s.length) {
        if (!.是空白或换行(s[pot])) {
            break;
        }
        ++pot;
    }
    return s[pot .. $];
}
dstring 文本转大写(dstring str) {
    const(dchar)[] 结果 = [];
    {
        for (int i = 0; i < str.length; ++i) {
            结果 = .追加!(const(dchar))(结果, .转为大写(str[i]));
        }
    }
    return ·to!(dstring)(结果);
}
dstring 文本转小写(dstring str) {
    const(dchar)[] 结果 = [];
    {
        for (int i = 0; i < str.length; ++i) {
            结果 = .追加!(const(dchar))(结果, .转为小写(str[i]));
        }
    }
    return ·to!(dstring)(结果);
}
bool 文本包含(dstring 主文本, dstring 子文本) {
    return .查找索引(主文本, 子文本) != -1;
}
bool 开始包含(dstring 主文本, dstring 子文本) {
    return .查找索引(主文本, 子文本) == 0;
}
bool 结尾包含(dstring 主文本, dstring 子文本) {
    if (主文本.length < 子文本.length) {
        return false;
    }
    dstring s = 主文本[主文本.length - 子文本.length .. $];
    return s == 子文本;
}
获取正规文件名函数_ 创建获取正规文件名函数(bool 使用区分大小写系统) {
    return 使用区分大小写系统 ? cast(获取正规文件名函数_)(·fd(&.不改变!(dstring))) : cast(获取正规文件名函数_)(·fd(&.文本转小写));
}
比较结果_ delegate(dstring, dstring) 获取文本比较器(bool 忽略大小写 = ··null!(bool)) {
    比较结果_ delegate(dstring, dstring) 比较器 = 忽略大小写 ? cast(比较结果_ delegate(dstring, dstring))(·fd(&.比较文本不区分大小写)) : cast(比较结果_ delegate(dstring, dstring))(·fd(&.比较文本区分大小写));
    return cast(比较结果_ delegate(dstring, dstring))(比较器);
}
T 不改变(T)(T id) {
    return id;
}
void 无序删除项目按索引(T)(ref T[] 数组, long 索引) {
    // Fill in the "hole" left at `index`.
    数组[索引] = 数组[数组.length - 1];
    数组 = 数组[0 .. $-1];
}
/** Remove the *first* occurrence of `item` from the 数组. */
bool 无序删除项目(T)(ref T[] 数组, T 项目) {
    return .无序删除第一项!(T)(数组, (T 元素) { return 元素 == 项目; });
}
/** Remove the *first* element satisfying `predicate`. */
bool 无序删除第一项(T)(ref T[] 数组, bool delegate(T) 谓词) {
    {
        for (int i = 0; i < 数组.length; ++i) {
            if (谓词(数组[i])) {
                .无序删除项目按索引!(T)(数组, i);
                return true;
            }
        }
    }
    return false;
}
void 列举插入和删除(T, U)(ref T[] 新项目组, U[] 旧项目组, 比较结果_ delegate(T, U) 比较器, void delegate(T) 插入, void delegate(U) 删除的, void delegate(U, T) 未改变的) {
    int 新索引 = 0;
    int 旧索引 = 0;
    size_t 新长度 = 新项目组.length;
    size_t 旧长度 = 旧项目组.length;
    while(新索引 < 新长度 && 旧索引 < 旧长度) {
        T 新项 = 新项目组[新索引];
        U 旧项 = 旧项目组[旧索引];
        比较结果_ 结果 = 比较器(新项, 旧项);
        if (结果 == 比较结果_.小于) {
            插入(新项);
            ++新索引;
        }
        else if (结果 == 比较结果_.大于) {
            删除的(旧项);
            ++旧索引;
        }
        else {
            未改变的(旧项, 新项);
            ++新索引;
            ++旧索引;
        }
    }
    while(新索引 < 新长度) {
        插入(新项目组[++新索引]);
    }
    while(旧索引 < 旧长度) {
        删除的(旧项目组[++旧索引]);
    }
}
bool 在规范组内查找(const(dchar) ch, const(long[]) 规范) {
    // Bail out quickly 如果 it couldn't possibly be in the 规范.
    if (ch < 规范[0]) {
        return false;
    }
    // Perform binary search in one of the Unich range 规范s
    long 低 = 0;
    long 高 = (cast()(规范.length));
    long 中 = (cast()(规范.length / 2));
    while(低 + 1 < 高) {
        中 = 低 + (高 - 低) / 2;
        // 中 has to be even to catch a range's beginning
        中 -= 中 % 2;
        if (规范[中] <= ch && ch <= 规范[中 + 1]) {
            return true;
        }
        if (ch < 规范[中]) {
            高 = 中;
        }
        else {
            低 = 中 + 2;
        }
    }
    return false;
}
/**
 * Performs a binary search, finding the index at which `value` occurs in `array`.
 * If no such index is found, returns the 2's-complement of first index at which
 * `array[index]` exceeds `value`.
 * @param 数组 A sorted array whose first element must be no larger than number
 * @param 值 The value to be searched for in the array.
 * @param 键选择 A callback used to select the search key from `value` and each element of
 * `array`.
 * @param 键比较 A callback used to compare two keys in a sorted array.
 * @param 偏移 An offset into `array` at which to start the search.
 */
long 二分搜索(T, U)(T[] 数组, T 值, U delegate(T) 键选择, 比较结果_ delegate(U, U) 键比较, long 偏移 = ··null!(long)) {
    return .二分搜索自选键!(T, U)(数组, 键选择(值), cast(U delegate(T))(键选择), cast(比较结果_ delegate(U, U))(键比较), 偏移);
}
/**
 * Performs a binary search, finding the index at which an object with `key` occurs in `array`.
 * If no such index is found, returns the 2's-complement of first index at which
 * `array[index]` exceeds `key`.
 * @param 数组 A sorted array whose first element must be no larger than number
 * @param 键 The key to be searched for in the array.
 * @param 键选择 A callback used to select the search key from each element of `array`.
 * @param 键比较 A callback used to compare two keys in a sorted array.
 * @param 偏移 An offset into `array` at which to start the search.
 */
long 二分搜索自选键(T, U)(T[] 数组, U 键, U delegate(T) 键选择, 比较结果_ delegate(U, U) 键比较, long 偏移 = ··null!(long)) {
    if ((数组 is ··null!(T[])) || 数组.length == 0) {
        return -1;
    }
    long 低 = 偏移 ? 偏移 : 0;
    long 高 = 数组.length - 1;
    while(低 <= 高) {
        long 中间 = 低 + ((高 - 低) >> 1);
        U 中间键 = 键选择(数组[中间]);
        switch (键比较(中间键, 键)) {
            case 比较结果_.小于: {
                低 = 中间 + 1;
                break;
            }
            case 比较结果_.等于: {
                return 中间;
            }
            case 比较结果_.大于: {
                高 = 中间 - 1;
                break;
            }
            default: break;
        }
    }
    return ~低;
}
U[dstring] 数组转词典(T, U)(T[] 数组, dstring delegate(T) 制作键, U delegate(T) 制作值) {
    U[dstring] 结果;
    foreach (T 值; 数组) {
        dstring 键 = 制作键(值);
        结果[键] = 制作值(值);
    }
    return 结果;
}
/** stableSortIndices */
size_t[] 稳定下标排序(T)(T[] 数组, size_t[] 下标组, 比较器_!(T) 比较器) {
    // sort indices by value then position
    下标组 = .排序!(size_t)(下标组, (size_t x, size_t y) { return 比较器(数组[x], 数组[y]); });
    return 下标组;
}
/**
 * Deduplicates an array that has already been sorted.
 */
/** deduplicateSorted */
T[] 排序的重复数据消除(T)(T[] 排序的数组, 比较器_!(T) 比较器) {
    if (排序的数组.length == 0) {
        return ··null!(T[]);
    }
    T 第一个 = 排序的数组[0];
    T[] 去重的数组 = [第一个];
    {
        for (int i = 1; i < 排序的数组.length; ++i) {
            T 下一个 = 排序的数组[i];
            switch (比较器(下一个, 第一个)) {
                case 比较结果_.等于: {
                    continue;
                }
                case 比较结果_.小于: {
                    // If `array` is sorted, `下一个` should **never** be less than `第一个`.
                    assert(false, "数组不是排序的."c);
                    continue;
                }
                default: break;
            }
            第一个 = 下一个;
            .追加!(T)(去重的数组, 第一个);
        }
    }
    return 去重的数组;
}
/** deduplicateRelational */
T[] 重复数据消除(T)(T[] 数组, 相等比较器_!(T) 相等比较器, 比较器_!(T) 比较器) {
    size_t[] 下标组 = .映射!(T, size_t)(数组, (T _, size_t i) { return i; });
    下标组 = .稳定下标排序!(T)(数组, 下标组, cast(比较器_!(T))(比较器));
    T 第一个 = 数组[下标组[0]];
    size_t[] 去重的 = [下标组[0]];
    {
        for (int i = 1; i < 下标组.length; ++i) {
            size_t 下标 = 下标组[i];
            T 项目 = 数组[下标];
            if (!相等比较器(第一个, 项目)) {
                去重的 = .追加!(size_t)(去重的, 下标);
                第一个 = 项目;
            }
        }
    }
    去重的 = .排序!(size_t)(去重的, cast(比较结果_ delegate(size_t, size_t))(·fd(&.比较器比较值)));
    return .映射!(size_t, T)(去重的, (size_t i, size_t _) { return 数组[i]; });
}
void 插入排序的(T)(ref T[] 排序数组, T 插入的, 比较器_!(T) 比较器) {
    if (排序数组.length == 0) {
        .追加!(T)(排序数组, 插入的);
    }
    else {
        long 插入索引 = .二分搜索!(T, T)(排序数组, 插入的, cast(T delegate(T))(·fd(&.不改变!(T))), cast(比较结果_ delegate(T, T))(比较器));
        if (插入索引 < 0) {
            T[] 前 = 排序数组[0 .. ~插入索引];
            T[] 后 = 排序数组[~插入索引 .. $];
            .追加!(T)(前, 插入的);
            .追加!(T)(前, 后);
            排序数组 = 前;
        }
    }
}
void 插入或替换排序的(T)(ref T[] 排序数组, T 插入的, 比较器_!(T) 比较器) {
    if (排序数组.length == 0) {
        .追加!(T)(排序数组, 插入的);
    }
    else {
        long 插入索引 = .二分搜索!(T, T)(排序数组, 插入的, cast(T delegate(T))(·fd(&.不改变!(T))), cast(比较结果_ delegate(T, T))(比较器));
        if (插入索引 < 0) {
            long 索引 = ~插入索引;
            if (索引 != 排序数组.length) {
                T I = 排序数组[索引];
                if (比较器(I, 插入的) == 比较结果_.等于) {
                    排序数组[索引] = 插入的;
                    return;
                }
            }
            T[] 前 = 排序数组[0 .. 索引];
            T[] 后 = 排序数组[索引 .. $];
            .追加!(T)(前, 插入的);
            .追加!(T)(前, 后);
            排序数组 = 前;
        }
    }
}
/** sortAndDeduplicate */
T[] 排序且去重(T)(ref T[] 数组, 比较器_!(T) 比较器, 相等比较器_!(T) 相等比较器) {
    if (数组 is ··null!(T[])) {
        return ··null!(T[]);
    }
    数组 = .排序的重复数据消除!(T)(.排序!(T)(数组, cast(比较结果_ delegate(T, T))(比较器)), (T a, T b) {
        bool ret = 相等比较器(a, b);
        if (ret) {
            return 比较结果_.等于;
        }
        return 比较结果_.大于;
    });
    return 数组;
}
/**
 * Gets the relative complement of `arrayA` with respect to `arrayB`, returning the elements that
 * are not present in `arrayA` but are present in `arrayB`. Assumes both arrays are sorted
 * based on the provided comparer.
 */
T[] 获取相对补码(T)(T[] arrayA = ··null!(T[]), T[] arrayB = ··null!(T[]), 比较器_!(T) comparer = ··null!(比较器_!(T))) {
    if ((arrayB is ··null!(T[])) || (arrayA is ··null!(T[])) || arrayB.length == 0 || arrayA.length == 0) {
        return arrayB;
    }
    T[] result = [];
    {
        int offsetA = 0;
        int offsetB = 0;
        loopB: for (; offsetB < arrayB.length; ++offsetB) {
            if (offsetB > 0) {
                // Ensure `arrayB` is properly sorted.
                assert(comparer(arrayB[offsetB], arrayB[offsetB - 1]) == 比较结果_.等于, "比较错误"c);
            }
            {
                loopA: for (int startA = offsetA; offsetA < arrayA.length; ++offsetA) {
                    if (offsetA > startA) {
                        // Ensure `arrayA` is properly sorted. We only need to perform this check if
                        // `offsetA` has changed since we entered the loop.
                        assert(comparer(arrayA[offsetA], arrayA[offsetA - 1]) == 比较结果_.等于, "比较错误"c);
                    }
                    比较结果_ 比较 = comparer(arrayB[offsetB], arrayA[offsetA]);
                    if (比较 == 比较结果_.小于) {
                        .追加!(T)(result, arrayB[offsetB]);
                        continue loopB;
                    }
                    if (比较 == 比较结果_.等于) {
                        continue loopB;
                    }
                    if (比较 == 比较结果_.大于) {
                        continue loopA;
                    }
                }
            }
        }
    }
    return result;
}
T[] addRange(T)(ref T[] to, T[] from, long start = 0, long end = 0) {
    if ((from is ··null!(T[])) || from.length == 0) {
        return to;
    }
    if (to is ··null!(T[])) {
        to = from[start .. end];
        return to;
    }
    start = start == 0 ? 0 : .toOffset!(T)(from, start);
    end = end == 0 ? from.length : .toOffset!(T)(from, end);
    {
        for (long i = start; i < end && i < from.length; ++i) {
            if (from[i] !is ··null!(T)) {
                .追加!(T)(to, from[i]);
            }
        }
    }
    return to;
}
/**
 * Gets the actual offset into an array for a relative offset. Negative offsets indicate a
 * position offset from the end of the array.
 */
long toOffset(T)(T[] array, long offset) {
    return offset < 0 ? array.length + offset : offset;
}
bool rangeEquals(T)(T[] array1, T[] array2, long pos, long end) {
    if ((array1 is ··null!(T[])) && (array2 is ··null!(T[]))) {
        return true;
    }
    if (((array1 is ··null!(T[])) || (array2 is ··null!(T[])))) {
        if (pos == 0 && end == 0) {
            return true;
        }
        return false;
    }
    if (pos > end) {
        return false;
    }
    if (pos == end) {
        return true;
    }
    long 最小长度 = .最小(array1.length, array2.length);
    if (end > 最小长度) {
        return false;
    }
    while(pos < end) {
        if (array1[pos] != array2[pos]) {
            return false;
        }
        ++pos;
    }
    return true;
}
T[] sameMap(T)(T[] array, T delegate(T, long) f) {
    if (array !is ··null!(T[])) {
        {
            for (int i = 0; i < array.length; ++i) {
                T item = array[i];
                T mapped = f(item, i);
                if (item != mapped) {
                    T[] result = array[0 .. i];
                    .追加!(T)(result, mapped);
                    for (++i; i < array.length; ++i) {
                        .追加!(T)(result, f(array[i], i));
                    }
                    return result;
                }
            }
        }
    }
    return array;
}
/** Remove an item from an array, moving everything to its right one space left. */
bool orderedRemoveItem(T)(ref T[] array, T item) {
    {
        for (int i = 0; i < array.length; ++i) {
            if (array[i] == item) {
                .orderedRemoveItemAt!(T)(array, i);
                return true;
            }
        }
    }
    return false;
}
/** Remove an item by index from an array, moving everything to its right one space left. */
void orderedRemoveItemAt(T)(ref T[] array, long index) {
    {
        // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`.
        for (long i = index; i < array.length - 1; ++i) {
            array[i] = array[i + 1];
        }
    }
    array = array[0 .. $-1];
}
void unorderedRemoveItemAt(T)(ref T[] array, long index) {
    // Fill in the "hole" left at `index`.
    array[index] = array[array.length - 1];
    array = array[0 .. $-1];
}
/** Remove the *first* occurrence of `item` from the array. */
bool unorderedRemoveItem(T)(ref T[] array, T item) {
    return .unorderedRemoveFirstItemWhere!(T)(array, (T element) { return element == item; });
}
/** Remove the *first* element satisfying `predicate`. */
bool unorderedRemoveFirstItemWhere(T)(ref T[] array, bool delegate(T) predicate) {
    {
        for (int i = 0; i < array.length; ++i) {
            if (predicate(array[i])) {
                .unorderedRemoveItemAt!(T)(array, i);
                return true;
            }
        }
    }
    return false;
}
映射类型_!(T) compose(T)(映射类型_!(T)[] args) {
    args = args.dup;
    return (T t) { return .reduceLeft!(映射类型_!(T), T)(args, (T u, 映射类型_!(T) f, 整数_ _) { return f(u); }, t); };
}
U reduceLeft(T, U)(T[] array, U delegate(U, T, long) f, U initial, long start = -1, long count = -1) {
    if ((array !is ··null!(T[])) && array.length > 0) {
        long size = array.length;
        if (size > 0) {
            long pos = start == -1 || start < 0 ? 0 : start;
            long end = count == -1 || pos + count > size - 1 ? size - 1 : pos + count;
            U result = initial;
            while(pos <= end) {
                result = f(result, array[pos], pos);
                ++pos;
            }
            return result;
        }
    }
    return initial;
}
T reduceLeft2(T)(T[] array, T delegate(T, T, long) f) {
    if ((array !is ··null!(T[])) && array.length > 0) {
        long size = array.length;
        if (size > 0) {
            int pos = 0;
            long end = size - 1;
            T result = array[pos];
            ++pos;
            while(pos <= end) {
                result = f(result, array[pos], pos);
                ++pos;
            }
            return result;
        }
    }
    return ··null!(T);
}
T[] append(T)(T[] to, T value = ··null!(T)) {
    if (value is ··null!(T)) {
        return to;
    }
    if (to is ··null!(T[])) {
        return [value];
    }
    .追加!(T)(to, value);
    return to;
}
bool arraysEqual(T)(T[] a, T[] b) {
    return a.length == b.length && .每个数组成员!(T)(a, (T x, size_t i) { return x == b[i]; });
}
V getOrUpdate(V)(词典_!(V) map, dstring key, V delegate() callback) {
    if (map.具有(key)) {
        return map.获取(key);
    }
    V value = callback();
    map.p·设置(key, value);
    return value;
}
int hexDigitValue(const(dchar) C) {
    static int[256] _llvm_LUT = [
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
        -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
    ];
    /* clang-format on */
    return _llvm_LUT[(cast(int)(C))];
}
字符_ 十六进制编码(ubyte n) {
    switch (n) {
        case 0: {
            return 字符_.数_0;
        }
        case 1: {
            return 字符_.数_1;
        }
        case 2: {
            return 字符_.数_2;
        }
        case 3: {
            return 字符_.数_3;
        }
        case 4: {
            return 字符_.数_4;
        }
        case 5: {
            return 字符_.数_5;
        }
        case 6: {
            return 字符_.数_6;
        }
        case 7: {
            return 字符_.数_7;
        }
        case 8: {
            return 字符_.数_8;
        }
        case 9: {
            return 字符_.数_9;
        }
        case 10: {
            return 字符_.A;
        }
        case 11: {
            return 字符_.B;
        }
        case 12: {
            return 字符_.C;
        }
        case 13: {
            return 字符_.D;
        }
        case 14: {
            return 字符_.E;
        }
        case 15: {
            return 字符_.F;
        }
        default: break;
    }
    return 字符_.空字符;
}
// 值类型
R bitTo(R, U)(U u) {
    R r;
    U u2 = u;
    .·memcpy(&r, &u2, u.sizeof);
    return r;
}
/// This function takes a 64-bit integer and returns the bit equivalent 小数64.
double BitsToDouble(ulong Bits) {
    return .bitTo!(double, ulong)(Bits);
}
/// This function takes a 32-bit integer and returns the bit equivalent 小数32.
float BitsToFloat(uint Bits) {
    return .bitTo!(float, uint)(Bits);
}
/// This function takes a 小数64 and returns the bit equivalent 64-bit integer.
/// Note that copying doubles around changes the bits of NaNs on some hosts,
/// notably x86, so this routine cannot be used if these bits are needed.
ulong DoubleToBits(double Double) {
    return .bitTo!(ulong, double)(Double);
}
/// This function takes a 小数32 and returns the bit equivalent 32-bit integer.
/// Note that copying floats around changes the bits of NaNs on some hosts,
/// notably x86, so this routine cannot be used if these bits are needed.
uint FloatToBits(float Float) {
    return .bitTo!(uint, float)(Float);
}
unittest {
    void main() {
        dstring str = "嘻爱上阿斯上蒂芬"d;
        long index = .从后查找索引(str, "嘻爱"d);
        assert(index == 0, "从后查找测试错误"c);
        index = .从后查找索引(str, "嘻爱上阿斯上蒂芬"d);
        assert(index == 0, "从后查找测试错误"c);
        index = .从后查找索引(str, "阿斯上蒂芬"d);
        assert(index == 3, "从后查找测试错误"c);
        index = .从后查找索引(str, "上"d);
        assert(index == 5, "从后查找测试错误"c);
    }
    main();
}
unittest {
    void main() {
        dstring str = "abcDeF"d;
        dstring str2 = "ABCdef"d;
        bool b = .相等文本不区分大小写(str, str2);
        assert(b, "相等文本不区分大小写函数错误"c);
    }
    main();
}
unittest {
    void main() {
        long[] arr = [1, 2, 2, 3, 3, 4];
        arr = .重复数据消除!(long)(arr, (整数_ a, 整数_ b) { return a == b; }, cast(比较器_!(long))(·fd(&.比较器比较值)));
        assert(arr.length == 4, "重复数据消除 长度 错误"c);
        assert(arr[0] == 1, "重复数据消除 0 错误"c);
        assert(arr[1] == 2, "重复数据消除 1 错误"c);
        assert(arr[2] == 3, "重复数据消除 2 错误"c);
        assert(arr[3] == 4, "重复数据消除 3 错误"c);
        .·writeln(arr);
    }
    main();
}
unittest {
    void main() {
        long[] arr = [1, 2, 2, 4];
        .插入排序的!(long)(arr, 3, cast(比较器_!(long))(·fd(&.比较器比较值)));
        .·writeln(arr);
    }
    main();
}
